package sparkml_study

import org.apache.spark.sql.SparkSession
import org.apache.spark.ml.feature.{HashingTF, IDF, IDFModel, Tokenizer}

object TeZhengTiQu {
  def main(args: Array[String]): Unit = {

    /*
    特征提取分为下面三种类型的特征提取
        1. 数值特征提取
    数值型数据是机器学习中最常见的特征类型，例如年龄、收入等。通常我们不需要对这些特征进行复杂的处理，但在有些情况下，可能需要对数值数据进行标准化、归一化或缩放。

    StandardScaler：将特征缩放至均值为 0，标准差为 1。
    MinMaxScaler：将特征缩放至指定的最小值和最大值之间（例如 [0, 1]）。
    MaxAbsScaler：将特征缩放至 [-1, 1] 范围，适用于包含负值的数据。
    2. 类别特征提取
    类别数据通常以字符串形式存在，像性别、城市等。为了能将这些类别数据用于机器学习模型，我们需要将它们转换成数字格式。Spark 提供了几种常见的编码方法：

    StringIndexer：将类别变量（如 "male", "female"）映射为整数值（例如 0, 1）。这种方法对于有序的类别数据（例如等级）特别有效。
    OneHotEncoder：将每个类别的特征转换成一个二进制向量。例如，假设有三个类别 {A, B, C}，则它们会被转换为三个新的二进制特征：{1, 0, 0}、{0, 1, 0}、{0, 0, 1}。OneHot 编码适用于无序的类别数据。
    3. 文本特征提取
    文本数据在许多机器学习任务中是常见的输入数据类型，Spark 提供了几种常见的文本特征提取方法：
     */

    val spark=SparkSession.builder()
      .master("local[*]")
      .appName("特征提取")
      .getOrCreate()


    //  创建一个集合，每个句子(sentences)代表一个文件
    val sentencesData=spark.createDataFrame(Seq(
      (0,"i heard abount spark and i love spark"),
      (0,"i wish java could use case calsses"),
      (1,"logistic regression models are neart")
    )).toDF("label","sentence")


    //  用Tokenizer把每个句子分解成单词,因为Tokenizer就是一个转换器，所以这里可以直接transform
    val tokenizer=new Tokenizer()
      .setInputCol("sentence")
      .setOutputCol("words")

    //  直接训练，分解成单词
    val wordsData=tokenizer.transform(sentencesData)

    wordsData.show(false)

    //  用HashingTF的transform()方法把每个"词袋"哈希成特征向量，这里设置的哈希表的桶数为2000
    val hashingTF=new HashingTF()
      .setInputCol("words")
      .setOutputCol("rawFeatures")
      .setNumFeatures(2000)

    //  训练
    val featurizedData=hashingTF.transform(wordsData)

    //  调用IDF方法来重新构造特征向量的规模，生成的变量idf是一个评估器，在特征向量上应用它的fit方法
    //  像下面这种没有fit之后的就叫做评估器
    val idf=new IDF()
      .setInputCol("rawFeatures")
      .setOutputCol("features")

    //  像这种fit之后的就叫做转化器
    val idfModel:IDFModel=idf.fit(featurizedData)

    //  使用转化器的transform方法，就可以得到每一个单词对应的TF-IDF度量值了
    val rescaledData=idfModel.transform(featurizedData)

    //  查看度量值结果
    rescaledData.select("features","label").show(false)








    spark.close()
  }

}
